/*
 * @Author: 缄默
 * @Date: 2021-09-17 22:58:56
 * @LastEditors: 缄默
 * @LastEditTime: 2021-12-13 20:00:44
 */

#include <iostream>
#include <string>

using namespace std;

//product

class Product {
private:
    string part1;
    string part2;
    string part3;
public:
    void setPart1(string str) {
        part1 = str;
    }
    void setPart2(string str) {
        part2 = str;
    }
    void setPart3(string str) {
        part3 = str;
    }
    Product() {
        cout << "Product is built" << endl;
    }
    void show() {
        cout << part1 << endl;
        cout << part2 << endl;
        cout << part3 << endl;
    }
};

//Builder

class Builder {
protected:
    Product* product;
public:
    //全是纯虚函数
    virtual void BuildPartA() = 0;
    virtual void BuildPartB() = 0;
    virtual void BuildPartC() = 0;
    virtual ~Builder() { }
    
    Builder() {
        product = new Product();
    }

    Product *GetProduct() {
        return product;
    }
};


//建造者1
class ConcreteBuilder1 : public Builder {
public:
    
    void BuildPartA() {
        product->setPart1("ConcreteBuilder1 part1");
    }

    void BuildPartB() {
        product->setPart2("ConcreteBuilder1 part2");
    }    

    void BuildPartC() {
        product->setPart3("ConcreteBuilder1 part3");

    }

};

//建造者2 采用第二种建造方法
class ConcreteBuilder2 : public Builder {
public:
    
    void BuildPartA() {
        product->setPart1("ConcreteBuilder2 part1");
    }

    void BuildPartB() {
        product->setPart2("ConcreteBuilder2 part2");
    }    

    void BuildPartC() {
        product->setPart3("ConcreteBuilder2 part3");

    }

};

class Director {
private:
    Builder *_builder;
public:
    Director(Builder *pBuilder) {
        _builder = pBuilder;
    }

    void Construct() {
        _builder->BuildPartA();
        _builder->BuildPartB();
        _builder->BuildPartC();
    }
};

int main() {
    auto builder = new ConcreteBuilder1();
    auto director = new Director(builder);
    director->Construct();
    Product *product = builder->GetProduct();
    product->show();

    delete product;
    delete builder;
    delete director;
    
    cout << "第二种建造方法" <<endl;
    auto builder2 = new ConcreteBuilder2();
    auto director2 = new Director(builder2);
    director2->Construct();
    Product *product2 = builder2->GetProduct();
    product2->show();
    delete product2;
    delete builder2;
    delete director2;

    return 0;
}
